/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package GUI;

import deteccao.ControleMouse;
import deteccao.DeteccaoMovimento;
import filtros.Filtro;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.util.ArrayList;
import javax.media.jai.PlanarImage;
import org.neuroph.core.NeuralNetwork;
import processamento.HistogramaLimiar;
import processamento.OperadorBinarizacao;
import processamento.OperadorBordas;
import processamento.OperadorErosaoDilatacao;
import processamento.OperadorGrayscale;
import processamento.OperadorSegmentaPele;
import processamento.SubtracaoImagens;

/**
 *
 * @author Igor
 */
public class CapturaImagens extends Thread {

    private ControleMouse mouse;
    ImagePanel painel;
    SwingCapture cap;
    BufferedImage img;
    PlanarImage imgProcessada;
    PlanarImage imgCenario;
    OperadorBordas bordas = new OperadorBordas();
    OperadorGrayscale gray = new OperadorGrayscale();
    OperadorBinarizacao bina = new OperadorBinarizacao();
    SubtracaoImagens sub = new SubtracaoImagens();
    HistogramaLimiar hist = new HistogramaLimiar();
    DeteccaoMovimento detecta = new DeteccaoMovimento();
    int limiarOtimo = 0;
    OperadorErosaoDilatacao dilat = new OperadorErosaoDilatacao();
    boolean erode = false;
    private Point pontoDireito;
    private NeuralNetwork NeuralNetwork;
    int contadorImagem=0;
    boolean changeDireita = false;
    String Evento ="";


    @Override
    public void run() {
       
        while(true) {
            if (painel!=null && cap!=null) {
                try {
                   img = cap.captura();
                   imgProcessada = PlanarImage.wrapRenderedImage(img);
                   if (img!=null) {
                    processaImagem(imgProcessada).getAsBufferedImage();
                    painel.set(PlanarImage.wrapRenderedImage(img));
                    painel.repaint();
                   }
                } catch(NullPointerException e) {
                }
            }
        }
    }

    public ImagePanel getPainel() {
        return painel;
    }

    public void setPainel(ImagePanel painel) {
        this.painel = painel;
    }

    public SwingCapture getCap() {
        return cap;
    }

    public void setCap(SwingCapture cap) {
        this.cap = cap;
    }

    private PlanarImage processaImagem(PlanarImage imgProcessada) {
     PlanarImage imgAuxiliar = OperadorSegmentaPele.segmentaPele(imgProcessada);
       gray.setImage(imgProcessada);
       imgProcessada = (gray.convertImageToGrayScale());

        if (imgCenario==null) {
          imgCenario = imgProcessada;
          SwingCapture.saveJPG(imgCenario.getAsBufferedImage(), "C://imagemCenario.jpg");
       }

      imgProcessada = sub.subtraiImagens(imgCenario,imgProcessada);

      limiarOtimo = hist.limiarOtimo(imgProcessada);
      bina.setImage(imgProcessada);
      imgProcessada = bina.binarizaImagem(limiarOtimo);
      gray.setImage(imgAuxiliar);
      imgAuxiliar = gray.convertImageToGrayScale();
      bina.setImage(imgAuxiliar);
      imgAuxiliar = bina.binarizaImagem(limiarOtimo);
      imgProcessada = sub.adicionaImagens(imgProcessada,imgAuxiliar);

      imgProcessada = dilat.fechamento(imgProcessada);
      imgProcessada = Filtro.filtroMediana(imgProcessada);

       ArrayList<Point> pontos  = detecta.geraBlobEsquerdo(imgProcessada);
       ArrayList<Point> pontos2 = detecta.geraBlobDireito(imgProcessada);


       Point limite = detecta.getPontoLimite();
       BufferedImage imagemClipped;

       painel.setLimite(limite);
       if (limite.x+25<=imgProcessada.getWidth() && limite.y+50<=imgProcessada.getHeight() && limite.x-25>=0) {
             imagemClipped = img.getSubimage(limite.x-25, limite.y, 50, 50);
             analisaGesto(imagemClipped);
       }


       this.painel.setPontoCursor(pontos);
       this.painel.setBlobs(pontos2);
       this.painel.setMouse(mouse);

       this.painel.detectaClique(Evento);
       changeDireita = painel.isChangeDireita();
       detecta.setChangeDireita(changeDireita);

       if(!pontos.isEmpty() && !pontos2.isEmpty()) {
           double proporcaoW = (double)((double)Toolkit.getDefaultToolkit().getScreenSize().width/(double)imgProcessada.getWidth());
           double proporcaoH = (double)((double)Toolkit.getDefaultToolkit().getScreenSize().height/(double)imgProcessada.getHeight());

          double movX = 0;
          double movY = 0;
           if (!changeDireita) {
               if (pontos.get(0).y<=pontos.get(1).y) {
                    movX = ((pontos.get(2).x-10)*proporcaoW);
                    movY = ((pontos.get(2).y)*proporcaoH);
               } else {
                   movX = ((pontos.get(3).x-10)*proporcaoW);
                   movY = ((pontos.get(3).y)*proporcaoH);
               }
           } else {
               if (pontos2.get(0).y<=pontos2.get(1).y) {
                    movX = ((pontos2.get(2).x-10)*proporcaoW);
                    movY = ((pontos2.get(2).y)*proporcaoH);
               } else {
                   movX = ((pontos2.get(3).x-10)*proporcaoW);
                   movY = ((pontos2.get(3).y)*proporcaoH);
               }
           }

          mouse.mouseMovimentacao((int)Math.round(movX),(int)Math.round(movY));
       }

       return imgProcessada;
    }


    public Point getPontoDireito() {
        return pontoDireito;
    }

    public void setPontoDireito(Point pontoDireito) {
        this.pontoDireito = pontoDireito;
    }

    public ControleMouse getMouse() {
        return mouse;
    }

    public void setMouse(ControleMouse mouse) {
        this.mouse = mouse;
    }

    BufferedImage createResizedCopy(Image originalImage,
                int scaledWidth, int scaledHeight,
                boolean preserveAlpha)
    {
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
                g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
        g.dispose();
        return scaledBI;
    }

   private void analisaGesto(BufferedImage imagemClipped) {
        double[] entradas = new double[2500];
        int pixel[] = new int[1];

        gray.setImage(PlanarImage.wrapRenderedImage(imagemClipped));
        imagemClipped = gray.convertImageToGrayScale().getAsBufferedImage();
        limiarOtimo = hist.limiarOtimo(PlanarImage.wrapRenderedImage(imagemClipped));
        bina.setImage(PlanarImage.wrapRenderedImage(imagemClipped));
        imagemClipped = bina.binarizaImagem(limiarOtimo).getAsBufferedImage();

        SwingCapture.saveJPG(imagemClipped, "C://imagens/clippada"+contadorImagem+".jpg");
        
        int count=0;
        Raster inputRaster = imagemClipped.getData();
        for (int i=0;i<50;i++) {
            for(int j=0;j<50;j++) {
                inputRaster.getPixel(i,j,pixel);
                entradas[count] = pixel[0];
                count++;
            }
        }


        NeuralNetwork.setInput(entradas);
        NeuralNetwork.calculate();
        
         //System.out.println(NeuralNetwork.getOutput()[0]+ " , "+ NeuralNetwork.getOutput()[1]);


            if (Math.abs(NeuralNetwork.getOutput()[0]-1)<=0.15 && Math.abs(NeuralNetwork.getOutput()[1]-1)<=0.15 && Math.abs(NeuralNetwork.getOutput()[2]-1)<=0.15)
                Evento="aberta";
            else if(Math.abs(NeuralNetwork.getOutput()[0] - 0) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[1] - 1) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[2] - 1) <= 0.15)
                Evento="fechada";
            else if(Math.abs(NeuralNetwork.getOutput()[0] - 1) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[1] - 0) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[2] - 0) <= 0.15)
                Evento="latino";
            else if(Math.abs(NeuralNetwork.getOutput()[0] - 0) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[1] - 0) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[2] - 1) <= 0.15)
                Evento="latinoinvertido";
            else if (Math.abs(NeuralNetwork.getOutput()[0] - 0) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[1] - 0) <= 0.15 && Math.abs(NeuralNetwork.getOutput()[2] - 0) <= 0.15)
                Evento="abertainvertida";
            else
                Evento="";
        


        contadorImagem++;

    }

    public NeuralNetwork getNeuralNetwork() {
        return NeuralNetwork;
    }

    public void setNeuralNetwork(NeuralNetwork NeuralNetwork) {
        this.NeuralNetwork = NeuralNetwork;
    }

    public boolean isChangeDireita() {
        return changeDireita;
    }

    public void setChangeDireita(boolean changeDireita) {
        this.changeDireita = changeDireita;
    }

}
